<?php

namespace app\middleware;

use app\helper\Config;
use Exception;
use GatewayWorker\Lib\Gateway;
use Illuminate\Support\Str;
use support\Log;
use think\helper\Arr;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

class SignAuth implements MiddlewareInterface
{

    protected Config $configRe;


    public function __construct()
    {
        $this->configRe = Config::getInstance();
    }


    /**
     * @throws Exception
     */
    public function process(Request $request, callable $handler): Response
    {

        $sign = $request->header('Sign');
        $timestamp = $request->header('Timestamp');

        Log::info($request->getRealIp() . '请求参数: ' . $request->url(), $request->all());

        if (empty($sign) || empty($timestamp)) {
            throw new Exception('签名校验失败', 500);
        }

        $paramsArr = $request->all();
        $paramsArr['timestamp'] = $timestamp;

        $params = '';

        try {
            foreach (Arr::sortRecursive($paramsArr) as $key => $param) {
                if (isset($param) && $param !== '') {
                    if (is_array($paramsArr[$key])) {
                        // 如果是数组就转字符串后操作
                        $params .= $key . json_encode($paramsArr[$key], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    } elseif (is_file($paramsArr[$key])) {
                        continue;
                    } else {
                        $params .= $key . $param;
                    }
                }
            }
        } catch (Exception) {
            throw new Exception('签名校验失败', 500);
        }

        // 加密算法密钥
        $signKey = $this->configRe->Get('system_sign_key', 'BQ6lB`Tj+79/]_4gLZteGpi');

        $signStr = Str::upper(md5(urlencode(urlencode($params)) . $signKey));

        if (trim($signStr) !== trim($sign)) {
            Log::info('签名字符串', [
                'client' => $sign,
                'server-str' => urlencode(urlencode($params)),
                'server' => $signStr,
            ]);
            if (config('app.debug')) {
                throw new Exception('签名校验失败' . $signStr, 500);
            } else {
                throw new Exception('签名校验失败', 500);
            }
        }

        // 修改websocket注册地址
        Gateway::$registerAddress = config('plugin.webman.gateway-worker.process.worker.constructor.config.registerAddress');

        return $handler($request);
    }
}